﻿using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using fc2editor.DataModel;
using fc2editor.Lua;

namespace fc2editor.Services
{
    public class FileService : IFileService
    {
        public string GamePath { get; private set; }

        public FileService(ICacheService cacheService)
        {
            this.cacheService = cacheService;
            GamePath = LoadGamePath();
        }

        #region IFileService Members

        public string[] GetPlanesFileNames()
        {
            var planesPath = Path.Combine(GamePath, @"Scripts\Database\planes");

            if (!Directory.Exists(planesPath))
                return new string[] { };

            return Directory.EnumerateFiles(planesPath, "*.lua").ToArray();
        }

        public string[] GetHelicopersFileNames()
        {
            var planesPath = Path.Combine(GamePath, @"Scripts\Database\helicopters");

            if (!Directory.Exists(planesPath))
                return new string[] { };

            return Directory.EnumerateFiles(planesPath, "*.lua").ToArray();
        }

        public string GetWeaponsFileName()
        {
            return Path.Combine(GamePath, @"Scripts\Database\db_weapons.lua");
        }

        public byte[] GetPicture(Weapon weapon)
        {
            return GetPictureByID(weapon.ID, weapon.Picture, PictureType.Weapon);
        }

        public byte[] GetPicture(Aircraft aircraft)
        {
            return GetPictureByID(aircraft.ID, aircraft.Picture, PictureType.Unit);
        }

        public void BackupAircraft(Aircraft aircraft)
        {
            var backupFullName = GenerateBackupFileName(aircraft.FileName);
            File.Copy(aircraft.FileName, backupFullName);
        }

        public void SaveAircraft(Aircraft aircraft)
        {
            BackupAircraft(aircraft);

            var serializer = new LuaSerializer();
            var lines = serializer.Serialize(aircraft);

            File.Delete(aircraft.FileName);
            File.WriteAllLines(aircraft.FileName, lines);

            //todo read all lines until pylons and add to temp file

            //next - write down all formatted pylons

            //next -- write down remaining lines from old files
        }

        #endregion

        #region Private methods

        private byte[] GetPictureByID(Guid id, string fileName, PictureType pType)
        {
            var picture = cacheService.GetPicture(id);
            if (picture == null)
            {
                picture = LoadPicture(fileName, pType);
                cacheService.CachePicture(id, picture);
            }

            return picture;
        }

        private byte[] LoadPicture(string fileName, PictureType pType)
        {
            var additionalPath = String.Empty;
            switch (pType)
            {
                case PictureType.Unit:
                    additionalPath = PlaneImagesPath;
                    break;
                case PictureType.Weapon:
                    additionalPath = WeaponImagesPath;
                    break;
                default:
                    throw new NotImplementedException();
            }

            var path = Path.Combine(GamePath, additionalPath);
            var filePath = Path.Combine(path, fileName);

            if (!File.Exists(filePath))
                return null;

            return File.ReadAllBytes(filePath);
        }

        private string GenerateBackupFileName(string oldFullName)
        {
            var nameWithoutExt = Path.GetFileNameWithoutExtension(oldFullName);
            var ext = Path.GetExtension(oldFullName);
            var path = Path.GetDirectoryName(oldFullName);
            var now = DateTime.Now;

            var backupPath = Path.Combine(path, "backup");
            if (!Directory.Exists(backupPath))
            {
                Directory.CreateDirectory(backupPath);
            }

            var backupFileName = String.Format("{0}_{1}_{2}_{3}_{4}_{5}_{6}{7}",
                nameWithoutExt, now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, ext);

            return Path.Combine(backupPath, backupFileName);
        }

        private string LoadGamePath()
        {
            XDocument doc = XDocument.Load(ConfigFileName);
            var e = doc.Descendants("game_path").FirstOrDefault();
            return e.Value;
        }

        #endregion

        private ICacheService cacheService;

        private const string WeaponImagesPath = @"BlackShark\data\images\Loadout\Weapon";
        private const string PlaneImagesPath = @"BlackShark\data\images\Loadout\Units";
        private const string ConfigFileName = "config.xml";
    }
}
